package com.chenxin.wms.process.inbound.impl;

import com.chenxin.common.annotation.WmsLogs;
import com.chenxin.common.constant.WmsConstants;
import com.chenxin.common.core.domain.ProcResult;
import com.chenxin.common.enums.WmsBusinessStatus;
import com.chenxin.common.enums.WmsTaskSubType;
import com.chenxin.common.enums.WmsTaskType;
import com.chenxin.common.utils.StringUtils;
import com.chenxin.wms.domain.IbDetailEntity;
import com.chenxin.wms.domain.LocationEntity;
import com.chenxin.wms.domain.StockEntity;
import com.chenxin.wms.domain.TaskEntity;
import com.chenxin.wms.domain.dto.WorkMaterialReturnParams;
import com.chenxin.wms.domain.po.SpuInfo;
import com.chenxin.wms.mapper.*;
import com.chenxin.wms.process.inbound.IProcWorkMaterialReturn;
import com.chenxin.wms.process.stock.IStockProcess;
import com.chenxin.wms.process.task.impl.TaskProcessImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

@Service
public class ProcWorkMaterialReturn implements IProcWorkMaterialReturn {

    @Autowired
    private IbDetailMapper ibDetailMapper;
    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private LocationMapper locationMapper;
    @Autowired
    private IbMasterMapper ibMasterMapper;
    @Autowired
    private IStockProcess stockProcess;
    @Autowired
    private TaskProcessImpl taskProcessImpl;

    @Transactional
    @WmsLogs(name = "车间退料入库登记")
    @Override
    public ProcResult executeProcess(WorkMaterialReturnParams dto) {
        if (dto == null) {
            return ProcResult.error("work_return_000", "请求参数不能为空");
        }

        // 0.获取相关参数
        Long ibDetailId = dto.getIbDetailId();
        String contNo = dto.getContNo();
        String reelId = dto.getRealId();
        String spuNo = dto.getSpuNo();
        BigDecimal returnQty = dto.getReturnQty();
        String lotNo = dto.getLotNo();
        Long creator = dto.getCreator();

        // 1.参数校验
        if (StringUtils.isNull(ibDetailId)) {
            return ProcResult.error("work_return_001", "入库明细ID不能为空");
        }
        if (StringUtils.isNull(contNo)) {
            return ProcResult.error("work_return_002", "容器编号不能为空");
        }
        if (StringUtils.isNull(spuNo)) {
            return ProcResult.error("work_return_003", "物料编号不能为空");
        }
        if (returnQty == null || returnQty.compareTo(BigDecimal.ZERO) <= 0) {
            return ProcResult.error("work_return_004", "退料数量不能小于等于0");
        }
        if (StringUtils.isNull(lotNo)) {
            return ProcResult.error("work_return_005", "批次号不能为空");
        }

        // 2.根据明细ID获取入库单明细信息
        IbDetailEntity detailInfo = ibDetailMapper.selectById(ibDetailId);
        if (detailInfo == null) {
            return ProcResult.error("work_return_006", "入库明细ID[" + ibDetailId + "]不存在");
        }
        // 3.验证物料信息
        SpuInfo spuInfo = spuMapper.selectSpuInfoByNo(spuNo);
        if (spuInfo == null) {
            return ProcResult.error("work_return_007", "物料[" + spuNo + "]不存在，请维护后再进行退料登记");
        }

        // 3.1.验证物料状态（spu_status=0为正常物料）
        if (spuInfo.getSpuStatus() != 0) {
            return ProcResult.error("work_return_008", "物料[" + spuNo + "]状态异常，不允许退料");
        }

        // 3.2.废弃物料或者未维护物料不允许退料
        if (spuInfo.getDelFlag().equals("2")) {
            return ProcResult.error("work_return_009", "物料[" + spuNo + "]已废弃，不允许退料");
        }

        // 4.验证退料数量是否合理（这里可以根据业务需求添加更多验证）
        // 检查是否超过计划退料数量等
        if (returnQty.compareTo(detailInfo.getIbPlanQty().subtract(detailInfo.getIbActualQty())) > 0) {
            return ProcResult.error("work_return_010", "退料数量[" + returnQty + "]大于剩余可退料数量[" +
                detailInfo.getIbPlanQty().subtract(detailInfo.getIbActualQty()) + "]");
        }

        // 5.获取退料暂存区位置
        Long zoneId = spuInfo.getZoneId(); // 物料默认库区
        LocationEntity returnStageLocation = locationMapper.selectById(zoneId);
        if (returnStageLocation == null) {
            return ProcResult.error("work_return_011", "未找到退料暂存区，请检查库区配置");
        }
        String stageLocationNo = returnStageLocation.getLocationNo();

        // 6.容器库存验证和处理
        List<StockEntity> existingStocks = stockProcess.getStocksByContNo(contNo);
        StockEntity existingStock = null;
        boolean hasOtherLocationStock = false;

        // 6.1.检查容器中是否已有库存
        for (StockEntity stock : existingStocks) {
            if (stock.getSpuNo().equals(spuNo) && stock.getLotNo().equals(lotNo)
                && stock.getLocationNo().equals(stageLocationNo)) {
                // 找到相同物料、批次且在退料暂存区的库存
                existingStock = stock;
            } else if (!stock.getLocationNo().equals(stageLocationNo)) {
                // 存在其他位置的库存
                hasOtherLocationStock = true;
            }
        }

        // 6.2.如果存在其他位置的库存，不允许混载
        if (hasOtherLocationStock && existingStock == null) {
            return ProcResult.error("work_return_012", "容器[" + contNo + "]已存在其他位置的库存，不允许混载");
        }

        // 7.处理库存记录 - 每次登记都创建新的库存记录，存储在退料暂存区
        StockEntity stockEntity = new StockEntity();
        stockEntity.setContNo(contNo);
        stockEntity.setLocationNo(stageLocationNo); // 退料暂存区
        stockEntity.setSpuNo(spuNo);
        stockEntity.setLotNo(lotNo);
        stockEntity.setStockQty(returnQty);
        stockEntity.setQualityStatus(WmsConstants.STOCK_QA_B); // 默认为合格品
        stockEntity.setIbDetailId(ibDetailId);
        stockEntity.setReelId(reelId);
        stockEntity.setCreator(creator);

        // 写入库存
        ProcResult resultStock = stockProcess.procWmsStockInsert(stockEntity);
        if (!resultStock.getCode().equals("0")) {
            throw new RuntimeException("库存写入失败: " + resultStock.getMessage());
        }

        // 8.每次登记都创建新的退料入库任务
        TaskEntity taskEntity = new TaskEntity();
        taskEntity.setTaskType(WmsTaskType.RECEIVE_IN.getCode());
        taskEntity.setTaskSubType(WmsTaskSubType.RETURN_IN.getCode()); // 退料入库子类型
        taskEntity.setTaskStatus(WmsConstants.TASK_STATUS_INIT);
        taskEntity.setFromContNo(contNo);
        taskEntity.setToContNo(contNo);
        taskEntity.setSpuNo(spuNo);
        taskEntity.setLotNo(lotNo);
        taskEntity.setPlanQty(returnQty);
        taskEntity.setMasterNo(detailInfo.getIbMasterNo());
        taskEntity.setDetailId(ibDetailId);
        taskEntity.setFromPosition(stageLocationNo);
        taskEntity.setCurPosition(stageLocationNo);
        taskEntity.setToPosition(stageLocationNo); // 暂存在退料暂存区
        taskEntity.setStockId(stockEntity.getStockId());
        taskEntity.setCreator(creator);

        // 写入任务
        ProcResult resultTask = taskProcessImpl.procWmsTaskInsert(taskEntity);
        if (!resultTask.getCode().equals("0")) {
            throw new RuntimeException("任务写入失败: " + resultTask.getMessage());
        }

        // 9.更新入库单据信息
        BigDecimal newActualQty = detailInfo.getIbActualQty().add(returnQty);


        // 9.1.判断退料是否完成（当退料数量等于计划退料数量时，标记为完成）
        if (newActualQty.compareTo(detailInfo.getIbPlanQty()) >= 0) {
            detailInfo.setIbDetailStatus(WmsBusinessStatus.IB_DETAIL_DONE.getCode()); // 完成
        } else {
            detailInfo.setIbDetailStatus(WmsBusinessStatus.IB_DETAIL_EXEC.getCode()); // 执行中
        }

        // 9.2.更新入库明细单据信息
        detailInfo.setIbActualQty(newActualQty);
        detailInfo.setUpdater(creator);
        //int resultDetail = ibDetailMapper.updateIbDetailByInfo(detailInfo);
        //if (resultDetail <= 0) {
        //    return ProcResult.error("work_return_015", "更新入库明细失败");
        //}

        // 9.3.判断入库主单是否完成（检查是否还有未完成的明细）
        //int unfinishedRows = ibDetailMapper.selectCountByMasterNo(detailInfo.getIbMasterNo());
        //if (unfinishedRows == 0) {
        //    // 所有明细都已完成，更新主单状态为完成
        //    ibMasterMapper.updateStatusByIbMasterNo(detailInfo.getIbMasterNo(),
        //        WmsBusinessStatus.IB_MASTER_DONE.getCode(), creator);
        //} else {
        //    // 还有未完成的明细，更新主单状态为执行中
        //    ibMasterMapper.updateStatusByIbMasterNo(detailInfo.getIbMasterNo(),
        //        WmsBusinessStatus.IB_MASTER_EXEC.getCode(), creator);
        //}

        return ProcResult.success("车间退料入库登记成功，退料数量：" + returnQty);
    }
}
